let localUsername = getUrlValue("userName"), toUser;
let websocket = null, peer = null, onTheLine = false, layer, laytpl, firstLogin = true;
let blobs = [], mediaRecorder, mimeType = 'video/webm';
var PeerConnection = window.RTCPeerConnection ||
  window.mozRTCPeerConnection ||
  window.webkitRTCPeerConnection;
let locIp = window.location.origin;
// 创建约束对象
const objData = {
  userList: [],//在线用户列表
  localStream: null,//本地视频流
  userPeerList: {},//用户peer列表rtc
  userInfo: {
    "userName": localUsername,
    "userId": uuid()
  },
  offerOption: {
    offerToReceiveAudio: 1,
    offerToReceiveVideo: 1
  },
  iceServers:{//穿透服务
    iceServers: [
        { url: ""}, //
        {
          url: '',
          credential: '',//密码
          username: ''//用户名
        }
    ]
  }
};
layui.use(['layer', 'laytpl'], function () {
  layer = layui.layer;
  laytpl = layui.laytpl;
  WebSocketInit();
  // 创建群聊
  $("#create-room").on("click", async function () {
    videoWithPartner()
  })
});
// 离开房间
$("#leave-room").on("click", async function () {
  await resetRtc();
  if (document.getElementById('localVideo').srcObject) {
    const videoTracks = document.getElementById('localVideo').srcObject.getVideoTracks();
    const audioTracks = document.getElementById('localVideo').srcObject.getAudioTracks();
    videoTracks.forEach(videoTrack => {
      // 关闭摄像头
      videoTrack.stop();
      document.getElementById('localVideo').srcObject.removeTrack(videoTrack);
    });
    audioTracks.forEach(audioTrack => {
      // 关闭麦克风
      audioTrack.stop();
      document.getElementById('localVideo').srcObject.removeTrack(audioTrack);
    });
  }
  $("#ManyToManyVideo").children("video").remove();
  objData.userList.forEach(ele => {
    let params = { "type": "onLeftRoom", "toUser": ele.userName, "fromUser": objData.userInfo.userName }
    websocket.send(JSON.stringify(params));
  });
})
//视频聊天
async function videoWithPartner() {
  await createNative();
  await nativeMedia();
  await initPeerList();
  let params = {
    type: "ManyToManyCommunicateVideo",
    toUser: "",
    fromUser: objData.userInfo.userName,
    msg: JSON.stringify(objData.userList)
  }
  websocket.send(JSON.stringify(params));
}
/* WebSocket */
function WebSocketInit() {
  //判断当前浏览器是否支持WebSocket
  if ('WebSocket' in window) {
    websocket = new WebSocket("wss://localhost:5500/wss/grouprtc/" + localUsername); //
  } else {
    alert("当前浏览器不支持WebSocket！");
  }

  //连接发生错误的回调方法
  websocket.onerror = function (e) {
    alert("WebSocket连接发生错误！");
  };

  //连接关闭的回调方法
  websocket.onclose = function () {
    console.error("WebSocket连接关闭");
  };

  //连接成功建立的回调方法
  websocket.onopen = function (e) {
    console.log("WebSocket连接成功");
  };

  //接收到消息的回调方法
  websocket.onmessage = async function (event) {
    if (!(JSON.parse(event.data).type)) {
      // 获取所有在线人员
      let userList = JSON.parse(event.data);
      let list = [];
      for (let index = 0; index < userList.length; index++) {
        const element = userList[index];
        if (element !== localUsername) {//去除当前用户
          list.push({
            userId: uuid(),
            userName: element
          })
        }
      }
      objData.userList = list;
    } else {
      let msg = JSON.parse(event.data);
      switch (msg.type) {
        case "ManyToManyCommunicateVideo"://发起群视频
          layer.confirm(`“${msg.fromUser}”邀请你加入群聊，是否加入？`, {
            btn: ['加入', '拒绝'] //按钮
          }, async function (index) {
            layer.close(index)
            await createNative();
            await nativeMedia();
            await initPeerList();
            objData.userList.forEach(ele => {
              let params = { "type": "onJoinRoom", "toUser": ele.userName, "fromUser": objData.userInfo.userName }
              websocket.send(JSON.stringify(params));
            });
          }, function () { });
          break;
        case "candidate":
          onIceCandidate(msg)
          break;
        case "offer":
          onOffer(msg)
          break;
        case "answer":
          onAnswer(msg)
          break;
        case "onJoinRoom":
          onCreateOffer(msg);
          break;
        case "onLeftRoom":
          // 离开房间
          removeEleVideo(msg.fromUser)
          break;
        default:
          break;
      }
    }

  }
}
//创建本地流全局放置
async function createNative() {
  objData.localStream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
}
//监听 Ice 候选
async function onIceCandidate(data) {
  let peerName = objData.userInfo.userName + "-" + data.fromUser;
  if (data.iceCandidate && objData.userPeerList[peerName]) {
    await objData.userPeerList[peerName].addIceCandidate(data.iceCandidate)
  }
}
//监听远端offer
async function onOffer(data) {
  let peerName = objData.userInfo.userName + "-" + data.fromUser;
  if (data.offer && objData.userPeerList[peerName]) {
    // 设置远程off
    await objData.userPeerList[peerName].setRemoteDescription(data.offer)
    // 接收端创建 answer
    let answer = objData.userPeerList[peerName].remoteDescription ? await objData.userPeerList[peerName].createAnswer() : "";

    //发送到呼叫端 answer
    let params = { type: "answer", "fromUser": objData.userInfo.userName, "toUser": data.fromUser, answer: answer };
    websocket.send(JSON.stringify(params));
    // 接收端设置本地 answer 描述
    objData.userPeerList[peerName].localDescription ? "" : await objData.userPeerList[peerName].setLocalDescription(answer);
  }

}
//监听远程响应
async function onAnswer(data) {
  let peerName = objData.userInfo.userName + "-" + data.fromUser;
  if (data.answer && objData.userPeerList[peerName]) {
    // 发送端 设置远程 answer 描述
    objData.userPeerList[peerName].remoteDescription ? "" : await objData.userPeerList[peerName].setRemoteDescription(data.answer);
  }

}
async function removeEleVideo(eleId) {
  if ($("#"+eleId).length==0) {
    return;
  }
  // 退出删除相应的video
  document.getElementById("ManyToManyVideo").removeChild(document.getElementById(eleId));
  if ($("#ManyToManyVideo").children("video").length == 1) {
    await resetRtc();
    if (document.getElementById('localVideo').srcObject) {
      const videoTracks = document.getElementById('localVideo').srcObject.getVideoTracks();
      const audioTracks = document.getElementById('localVideo').srcObject.getAudioTracks();
      videoTracks.forEach(videoTrack => {
        // 关闭摄像头
        videoTrack.stop();
        document.getElementById('localVideo').srcObject.removeTrack(videoTrack);
      });
      audioTracks.forEach(audioTrack => {
        // 关闭麦克风
        audioTrack.stop();
        document.getElementById('localVideo').srcObject.removeTrack(audioTrack);
      });
    }
    $("#ManyToManyVideo").children("video").remove();
  }
}
// 本地视频流打开
function nativeMedia() {
  let ele = document.getElementById("ManyToManyVideo");
  let video = document.createElement('video');
    video.controls = false;
    video.autoplay = true;
    video.muted = true;
    video.width = 300;
    video.height = 300;
    video.playsinline = true;
    video.id = "localVideo";
  // 旧的浏览器可能没有srcObject
  if ("srcObject" in video) {
    video.srcObject = objData.localStream;
  } else {
    video.src = window.URL.createObjectURL(objData.localStream);
  }
  ele.append(video);
}
// 渲染用户list
async function initPeerList() {
  objData.userPeerList = {};
  let localUsername = objData.userInfo.userName;
  objData.userList.forEach(ele => {
    if (objData.userInfo.userName !== ele.userName) {
      let peerName = localUsername + "-" + ele.userName;
      initPeer(peerName, ele);
    }
  });
}
//初始化 RTC
function initPeer(peerName, e) {
  let peer_tep = new PeerConnection(objData.iceServers);
  peer_tep.addStream(objData.localStream);
  peer_tep.onicecandidate = function (event) {
    if (event.candidate) {
      let params = { "type": 'candidate', "fromUser": objData.userInfo.userName, "toUser": e.userName, "iceCandidate": event.candidate };
      websocket.send(JSON.stringify(params));
    } else {
      // console.log("ICE收集已经完成")
    }
  };
  peer_tep.onaddstream = (event) => {
    createEleVideo(event.stream, e.userName)
  };
  objData.userPeerList[peerName] = peer_tep;
}
// 重置rtc
async function resetRtc() {
  Object.keys(objData.userPeerList).forEach((key) => {
    let peer = objData.userPeerList[key];
    peer.ontrack = null;
    peer.onremovetrack = null;
    peer.onremovestream = null;
    peer.onicecandidate = null;
    peer.oniceconnectionstatechange = null;
    peer.onsignalingstatechange = null;
    peer.onicegatheringstatechange = null;
    peer.onnegotiationneeded = null;

    peer.close();
    peer = null;
  })
}
//追加视频
function createEleVideo(stream, d) {
  let ele = document.getElementById("ManyToManyVideo");
  let old = document.getElementById(d);

  if (old) {
    old.srcObject = stream;
  } else {
    let video = document.createElement('video');
    video.controls = false;
    video.autoplay = true;
    video.width = 300;
    video.height = 300;
    video.playsinline = true;
    video.id = d;
    video.srcObject = stream;
    video.className = "group-video"
    ele.append(video);
  }
}
//创建连接
async function onCreateOffer(d) {
  // 收到加入消息之后创建
  console.log("开始创建offer")
  let peerName = objData.userInfo.userName + "-" + d.fromUser;
  if (objData.userPeerList[peerName]) {
    console.log(d)
    //创建offer
    let offer = await objData.userPeerList[peerName].createOffer(objData.offerOption);

    
    let params = { type: "offer", "fromUser": objData.userInfo.userName, "toUser": d.fromUser, offer: offer };
    //远程发送offer给加入的客户端
    websocket.send(JSON.stringify(params));
    //设置本地描述
    objData.userPeerList[peerName].localDescription?"":await objData.userPeerList[peerName].setLocalDescription(offer);
  }
}
// 获取地址栏参数
function getUrlValue(name) {
  var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
  var r = window.location.search.substring(1).match(reg);
  if (r != null) return decodeURI(r[2]);
  return null;
}
// 生成唯一id
function uuid(len, radix) {
  var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
  var uuid = [], i;
  radix = radix || chars.length;

  if (len) {
    // Compact form
    for (i = 0; i < len; i++) {
      uuid[i] = chars[0 | Math.random() * radix];
    }
  } else {
    // rfc4122, version 4 form
    var r;

    // rfc4122 requires these characters
    uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
    uuid[14] = '4';

    // Fill in random data. At i==19 set the high bits of clock sequence as
    // per rfc4122, sec. 4.1.5
    for (i = 0; i < 36; i++) {
      if (!uuid[i]) {
        r = 0 | Math.random() * 16;
        uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
      }
    }
  }
  return uuid.join('');
}
